using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using GameStateManagementSample.Classes;
//using polytest.Poly;

namespace PolyDecomp
{

    public class Polygon
    {

        //public float[] x;
        //public float[] y;
        //public int nVertices;
        public List<Vector2> vertices;

        public Polygon(List<Vector2> vectors)
        {
            //nVertices = _x.Length;
            ////    println("length "+nVertices);
            //x = new float[nVertices];
            //y = new float[nVertices];
            //for (int i = 0; i < nVertices; ++i)
            //{
            //    x[i] = _x[i];
            //    y[i] = _y[i];
            //}

            vertices = new List<Vector2>(vectors);

        }

        public Polygon(float[] _x, float[] _y)
        {
            var nVertices = _x.Length;
            vertices = new List<Vector2>();
            //    println("length "+nVertices);
            //x = new float[nVertices];
            //y = new float[nVertices];
            for (int i = 0; i < nVertices; ++i)
            {
                vertices.Add(new Vector2(_x[i], _y[i]));

            }



        }

        public Polygon(Triangle t)
        {
            vertices = new List<Vector2>();
            vertices.Add(t.v1);
            vertices.Add(t.v2);
            vertices.Add(t.v3);
        }

        public void set(Polygon p)
        {
            //nVertices = p.nVertices;
            //x = new float[nVertices];
            //y = new float[nVertices];
            //for (int i = 0; i < nVertices; ++i)
            //{
            //    x[i] = p.x[i];
            //    y[i] = p.y[i];
            //}
            vertices = new List<Vector2>(p.vertices);
        }

        /*
         * Assuming the polygon is simple, checks
         * if it is convex.
         */
        public bool isConvex()
        {
            var nVertices = vertices.Count;
            bool isPositive = false;
            for (int i = 0; i < nVertices; ++i)
            {
                int lower = (i == 0) ? (nVertices - 1) : (i - 1);
                int middle = i;
                int upper = (i == nVertices - 1) ? (0) : (i + 1);
                var d0 = vertices[middle] - vertices[lower];
                var d1 = vertices[upper] - vertices[middle];
                //float dx0 = x[middle] - x[lower];
                //float dy0 = y[middle] - y[lower];
                //float dx1 = x[upper] - x[middle];
                //float dy1 = y[upper] - y[middle];
                float cross = d0.X * d1.Y - d1.X * d0.Y;
                //Cross product should have same sign
                //for each vertex if poly is convex.
                bool newIsP = (cross > 0) ? true : false;
                if (i == 0)
                {
                    isPositive = newIsP;
                }
                else if (isPositive != newIsP)
                {
                    return false;
                }
            }
            return true;
        }


        public bool isGood()
        {
            // var nVertices = vertices.Count;

            var center = GeometryHelper.Compute2DPolygonCentroid(vertices);
            bool intersects = false;
            //Vector2 last = vertices.Last();
            foreach (Vector2 vert in vertices)
            {


                Vector2 v2 = vertices.Last();
                foreach (Vector2 v1 in vertices)
                {
                    intersects = GeometryHelper.TestLinesIntersectExclusive(center, vert, v1, v2);
                    if (intersects)
                    {
                        return false;
                    }
                    v2 = v1;
                }

            }
            //bool isPositive = false;

            //for (int i = 0; i < nVertices; ++i)
            //{
            //    int lower = (i == 0) ? (nVertices - 1) : (i - 1);
            //    int middle = i;
            //    int upper = (i == nVertices - 1) ? (0) : (i + 1);
            //    var d0 = vertices[middle] - vertices[lower];
            //    var d1 = vertices[upper] - vertices[middle];
            //    //float dx0 = x[middle] - x[lower];
            //    //float dy0 = y[middle] - y[lower];
            //    //float dx1 = x[upper] - x[middle];
            //    //float dy1 = y[upper] - y[middle];
            //    float cross = d0.X * d1.Y - d1.X * d0.Y;
            //    //Cross product should have same sign
            //    //for each vertex if poly is convex.
            //    bool newIsP = (cross > 0) ? true : false;
            //    if (i == 0)
            //    {
            //        isPositive = newIsP;
            //    }
            //    else if (isPositive != newIsP)
            //    {
            //        return false;
            //    }
            //}
            return true;
        }


        /*
         * Tries to add a triangle to the polygon.
         * Returns null if it can't connect properly.
         * Assumes bitwise equality of join vertices.
         */
        public Polygon add(Triangle t)
        {
            var nVertices = vertices.Count;
            //First, find vertices that connect
            int firstP = -1;
            int firstT = -1;
            int secondP = -1;
            int secondT = -1;
            //    println("nVertices: "+this.nVertices);
            for (int i = 0; i < nVertices; i++)
            {
                if (t.v1 == vertices[i])
                {
                    //        println("found p0");
                    if (firstP == -1)
                    {
                        firstP = i; firstT = 0;
                    }
                    else
                    {
                        secondP = i; secondT = 0;
                    }
                }
                else if (t.v2 == vertices[i])
                {
                    //        println("found p1");
                    if (firstP == -1)
                    {
                        firstP = i; firstT = 1;
                    }
                    else
                    {
                        secondP = i; secondT = 1;
                    }
                }
                else if (t.v3 == vertices[i])
                {
                    //        println("found p2");
                    if (firstP == -1)
                    {
                        firstP = i; firstT = 2;
                    }
                    else
                    {
                        secondP = i; secondT = 2;
                    }
                }
                else
                {
                    //        println(t.v1+" "+t.y[0]+" "+t.v2+" "+t.y[1]+" "+t.v3+" "+t.y[2]);
                    //        println(x[0]+" "+y[0]+" "+x[1]+" "+y[1]);
                }
            }
            //Fix ordering if first should be last vertex of poly
            if (firstP == 0 && secondP == nVertices - 1)
            {
                firstP = nVertices - 1;
                secondP = 0;
            }

            //Didn't find it
            if (secondP == -1) return null;

            //Find tip index on triangle
            int tipT = 0;
            if (tipT == firstT || tipT == secondT) tipT = 1;
            if (tipT == firstT || tipT == secondT) tipT = 2;

            Vector2 vert = tipT == 0 ? t.v1 : tipT == 1 ? t.v2 : t.v3;

            float[] newx = new float[nVertices + 1];
            float[] newy = new float[nVertices + 1];
            //List<Vector2> newVert = new List<Vector2>(vertices);
            //newVert.Insert(firstP, vert);

            int currOut = 0;
            for (int i = 0; i < nVertices; i++)
            {
                newx[currOut] = vertices[i].X;
                newy[currOut] = vertices[i].Y;
                if (i == firstP)
                {
                    ++currOut;
                    newx[currOut] = vert.X;
                    newy[currOut] = vert.Y;
                }
                ++currOut;
            }
            return new Polygon(newx, newy);
        }

        //public void draw(SpriteBatch sb)
        //{
        //    draw(sb);
        //}

        public void draw(SpriteBatch sb)
        {
            //    fill(fll);
            //noFill();
            //stroke(strk);
            //beginShape(POLYGON);
            //for (int i = 0; i < x.length; i++)
            //{
            //    vertex(x[i], y[i]);
            //}
            //endShape();

            //for (int i = 0; i < x.Length; i++)
            //{
            //    //vertex(x[i], y[i]);
            //    // LineBatchTester.LineBatch.DrawLine(sb, Color.Red, new Vector2(x[i], y[i]), new Vector2(x[i + 1], y[i + 1]));
            //    if (i < x.Length - 1)
            //    {
            //        LineBatchTester.LineBatch.DrawLine(sb, Color.Green, new Vector2(x[i], y[i]), new Vector2(x[i + 1], y[i + 1]));
            //        //line(x[i], y[i], x[i + 1], y[i + 1]); 
            //    }
            //    else
            //    {
            //        LineBatchTester.LineBatch.DrawLine(sb, Color.Green, new Vector2(x[i], y[i]), new Vector2(x[0], y[0]));
            //        //line(x[i], y[i], x[0], y[0]);
            //    }
            //}

            Vector2 last = vertices.Last();
            foreach (Vector2 vert in vertices)
            {
                LineBatchTester.LineBatch.DrawLine(sb, Color.Green, vert, last);

                last = vert;
            }


        }

    }
}